<?php

namespace app\api\service\Activity;

use addons\xyb\XypHelper;
use app\api\service\DynamicService;
use app\common\model\marketing\Association;
use app\common\model\marketing\AssociationJobs;
use app\common\model\marketing\AssociationProgress;
use app\common\model\marketing\AssociationUsers;
use think\Db;
use think\Log;

class AssociationJobsDetectionService
{
    /**
     * 检测动态是否匹配任务规则
     *
     *
     * @params int $jobs_id 任务ID
     * @params int $trends_id 动态ID
     */
    /**
     * 根据任务ID和动态ID处理关联任务进度
     *
     * @param string $jobs_id 任务ID，经过格式化处理的JSON字符串
     * @param int $trends_id 动态ID
     * @return array 返回处理结果
     */
    public static function index($jobs_id, $trends_id)
    {
        try {
            // 验证输入参数
            if (!is_numeric($trends_id)) {
                return ['status' => false, 'message' => 'Invalid input parameters'];
            }
            // 解析任务ID字符串为数组
            $jobs_info = self::formatJsonUniqueIdStringToArray($jobs_id);

            // 验证任务ID是否存在
            if (!isset($jobs_info['jobs_id']) || !$jobs_info['jobs_id']) {
                return ['status' => false, 'message' => 'Job ID not found'];
            }
            $jobs_id = intval($jobs_info['jobs_id']);
            // 验证规则键是否存在
            if (!isset($jobs_info['method']) || !$jobs_info['method']) {
                return ['status' => false, 'message' => 'Method key not found'];
            }
            /* ------ 动态活动 ------ */
            if ($jobs_info['method'] == 'DynamicService') {
                return DynamicService::match($jobs_id, $trends_id, $jobs_info);
            }
            $method = ($jobs_info['method']);
            // 验证规则键是否存在
            if (!isset($jobs_info['rules_key']) || !$jobs_info['rules_key']) {
                return ['status' => false, 'message' => 'Rules key not found'];
            }
            $rules_key = $jobs_info['rules_key'];
            if ($method == 2) {
                /* ------ 日常任务 ------ */
                return self::daily($jobs_id, $trends_id, $jobs_info);
            }
            // 定义查询字段
            $fields = [
                'jobs' => 'id,association_id,start_time,end_time,involved_days,execute_days,activity_method,get_limit,examine_method,
            grant_agent_id,grant_users_id,participation_rules,reward_method,reward_point,reward_coupons_id,grant_status,status,label_level',
                'trends' => 'id,detail,images,mp4_file,huati_text,circle_id,user_id,goods_id,goods_title'
            ];
            // 查询任务信息
            $jobs = AssociationJobs::field($fields['jobs'])->where('id', $jobs_id)->where('activity_method', $method)->find();
            if (!$jobs) {
                return ['status' => false, 'message' => 'Job not found'];
            }
            // 检查任务是否已结束
            if ($jobs->start_time > time() || $jobs->end_time < time()) {
                return ['status' => false, 'message' => 'Job has ended'];
            }
            // 查询动态信息
            $trends = \app\common\model\Trends::field($fields['trends'])->where('id', $trends_id)->find();
            if (!$trends) {
                return ['status' => false, 'message' => 'Trends not found'];
            }
            // 获取用户报名状态
            $jobs_enroll_status = AssociationUsers::getUsersJobsEnrollStatus($jobs->association_id, $trends->user_id, $jobs_id);
            // 用户未报名
            if (!$jobs_enroll_status['enroll_status']) {
                return ['status' => false, 'message' => 'User not enrolled'];
            }
            // 用户状态已结束
            if ($jobs_enroll_status['grant_status']) {
                return ['status' => false, 'message' => 'User status has ended'];
            }
            // 动态已完成
            if (AssociationProgress::where('trends_id', $trends_id)->where('grant_status', 1)->find()) {
                return ['status' => false, 'message' => 'Trends already completed'];
            }
            // 解析参与规则
            $participation_rules = XypHelper::formatJsonStringToArray($jobs->participation_rules);
            // 根据规则键过滤参与规则
            $record_found = array_filter($participation_rules, function ($record) use ($rules_key) {
                return $record['__key'] == $rules_key;
            });
            // 获取过滤后的第一条记录
            $record_found = array_values($record_found);
            if (!$record_found = (isset($record_found[0]) && $record_found[0])) {
                return ['status' => false, 'message' => 'No matching rule found'];
            }
            // 处理动态规则
            $params = self::ProcessingTrendsRules($record_found, $trends);
            // 确定发放状态
            $examine_time = 0;
            if ($jobs->examine_method == 2) {
                $grant_status = 0;
                $examine_stated = 0;
            } else {
                if ($params['stated'] === true) {
                    $grant_status = 1;
                    $examine_stated = 3;
                    $examine_time = date('Y-m-d H:i:s');
                } else {
                    $grant_status = 2;
                    $examine_stated = 4;
                    $examine_time = date('Y-m-d H:i:s');
                }
            }
            // 创建用户关联任务进度记录
            AssociationProgress::createUsersAssociationProgress([
                'association_id' => $jobs->association_id,
                'jobs_id' => $jobs->id,
                'circle_id' => $trends->circle_id,
                'activity_method' => $jobs->activity_method,
                'user_id' => $trends->user_id,
                'trends_id' => $trends_id,
                'trends_type' => $params['type'],
                'rules' => XypHelper::formatArrayToString($record_found),
                'association_key' => $rules_key,
                'type' => 1,
                'grant_status' => $grant_status,
                'status' => $examine_stated,
                'examine_time' => $examine_time,
                'trends_detail' => XypHelper::formatArrayToString($trends),
                'detection_res' => XypHelper::formatArrayToString($params)
            ]);
            return ['status' => true, 'message' => 'Success'];
        } catch (\Exception $e) {
            // 记录日志
            Log::error('Error in index: ' . $e->getMessage());
            return ['status' => false, 'message' => 'Internal server error' . $e->getMessage()];
        }
    }

    public static function daily($jobs_id, $trends_id, $jobs_info)
    {
        try {
            // 定义查询字段
            $fields = [
                'jobs' => 'id,examine_method,participation_rules,reward_method,reward_point,youth_point,reward_coupons_id,
        push_method,talk_id,association_id,__key,start_time,end_time,activity_method',
                'trends' => 'id,title,detail,images,mp4_file,huati_text,circle_id,user_id,goods_id,goods_title,hy_text',
                'association' => 'id,start_time,end_time,status,examine_method,category_id,grant_status'
            ];
            // 查询任务信息
            $jobs = AssociationJobs::field($fields['jobs'])->where('id', $jobs_id)->where('activity_method', 2)
                ->where('grant_status', 1)->where('status', 1)->find();
            if (!$jobs) {
                return ['status' => false, 'message' => 'Job not found'];
            }
            if ($jobs->start_time && $jobs->end_time) {
                // 检查任务是否已结束
                if ($jobs->start_time > time() || $jobs->end_time < time()) {
                    return ['status' => false, 'message' => 'Job has ended'];
                }
            }
            //检测活动状态
            $association = Association::field($fields['association'])->where('id', $jobs->association_id)
                ->where('grant_status', 1)->where('status', 1)->find();
            if (!$jobs) {
                return ['status' => false, 'message' => 'Job not found'];
            }
            if ($association->start_time > time() || $association->end_time < time()) {
                return ['status' => false, 'message' => 'Association has ended'];
            }
            // 查询动态信息
            $trends = \app\common\model\Trends::field($fields['trends'])->where('id', $trends_id)->find();
            if (!$trends) {
                return ['status' => false, 'message' => 'Trends not found'];
            }
            // 获取用户报名状态,用户已参与
            if (AssociationProgress::hasUsersJobsIsEnrollParticipate($trends->user_id, $jobs_id)) {
                return ['status' => false, 'message' => 'User already enrolled'];
            }
            $examine_time = 0;
            // 处理动态规则
            $params = self::ProcessingDailyTrendsRules($jobs, $trends);
            // 确定发放状态examine_method = 2 人工审核
            if ($jobs->examine_method == 2) {
                $grant_status = 0;
                $examine_stated = 0;
            } else {
                if ($params['stated'] === true) {
                    $grant_status = 2;
                    $examine_stated = 4;
                    $examine_time = date('Y-m-d H:i:s');
                } else {
                    $grant_status = 1;
                    $examine_stated = 5;
                    $examine_time = date('Y-m-d H:i:s');
                }
            }
            Db::startTrans();
            // 创建用户关联任务进度记录
            $res = AssociationProgress::createUsersAssociationProgress([
                'association_id' => $jobs->association_id,
                'jobs_id' => $jobs->id,
                'circle_id' => $trends->circle_id,
                'activity_method' => $jobs->activity_method,
                'user_id' => $trends->user_id,
                'trends_id' => $trends_id,
                'trends_type' => $params['type'],
                'rules' => XypHelper::formatArrayToString($jobs->participation_rules),
                'association_key' => $jobs->__key,
                'type' => 1,
                'grant_status' => $grant_status,
                'status' => $examine_stated,
                'examine_time' => $examine_time,
                'trends_detail' => XypHelper::formatArrayToString($trends),
                'detection_res' => XypHelper::formatArrayToString($params)
            ]);
            if (!$res) {
                Db::rollback();
                return ['status' => false, 'message' => 'Internal server error'];
            }
            if ($examine_stated === 4) {
                /*发放奖励*/
                AssociationProgress::examineProgress($res, 1, 2, 0);
            }
            $trends->ass_jobs_id = $res;
            $trends->ass_jobs_source = 1;
            $trends->is_displayed = 2;
            $trends->save();
            Db::commit();
            return ['status' => true, 'message' => 'Success'];
        } catch (\Exception $e) {
            // 记录日志
            Log::error('Error in index: ' . $e->getMessage());
            return ['status' => false, 'message' => 'Internal server error' . $e->getMessage()];
        }
    }

    /**
     * 处理动态规则
     *
     * 该方法用于根据记录和动态信息，判断是否满足特定的规则条件
     * 主要检查视频、图文和文本动态是否符合相应的规则，包括话题匹配、文本长度、图片数量等
     *
     * @param array $record_found 包含规则信息的数组
     * @param object $trends 动态对象，包含动态的相关信息
     *
     * @return array 包含规则检查结果的数组，如是否满足规则、动态类型和提示消息
     */
    protected static function ProcessingTrendsRules($record_found, $trends)
    {
        $detail_text_length = mb_strlen($trends->detail ?? '', 'utf-8');
        $type = $trends->mp4_file ? 'video' : (($image_length = XypHelper::stringToArray($trends->images, ',')) ? 'image' : 'text');
        $stated = true;
        $msg = '检查通过';
        switch ($type) {
            case 'video':
                if (!isset($record_found['video_stated']) || intval($record_found['video_stated']) < 1) {
                    $stated = false;
                    $msg = '未开启视频规则';
                } elseif (!self::ProcessingTrendsTaskRules($record_found, $trends->huati_text, 'video')) {
                    $stated = false;
                    $msg = '视频动态话题未匹配';
                } elseif (isset($record_found['video_length']) && intval($record_found['video_length']) > $detail_text_length) {
                    $stated = false;
                    $msg = '视频动态文本字数不足';
                }
                break;
            case 'image':
                if (!isset($record_found['image_stated']) || intval($record_found['image_stated']) < 1) {
                    $stated = false;
                    $msg = '未开启图文规则';
                } elseif (!self::ProcessingTrendsTaskRules($record_found, $trends->huati_text, 'image')) {
                    $stated = false;
                    $msg = '图文动态话题未匹配';
                } elseif (isset($record_found['image_num']) && intval($record_found['image_num']) > count($image_length)) {
                    $stated = false;
                    $msg = '图文动态图片数量不足';
                } elseif (isset($record_found['image_length']) && intval($record_found['image_length']) > $detail_text_length) {
                    $stated = false;
                    $msg = '图文动态文本字数不足';
                }
                break;
            case 'text':
                if (!isset($record_found['text_stated']) || intval($record_found['text_stated']) < 1) {
                    $stated = false;
                    $msg = '未开启文本规则';
                } elseif (!self::ProcessingTrendsTaskRules($record_found, $trends->huati_text, 'text')) {
                    $stated = false;
                    $msg = '文本动态话题未匹配';
                } elseif (isset($record_found['text_length']) && intval($record_found['text_length']) > $detail_text_length) {
                    $stated = false;
                    $msg = '文本动态文本字数不足';
                }
                break;
        }

        return ['stated' => $stated, 'type' => $type, 'msg' => $msg];
    }

    /**
     * 处理动态任务规则
     *
     * 此函数用于判断动态是否符合给定的话题规则它检查动态是否绑定了特定的话题，
     * 如果绑定了，则根据动态的类型（如文本、图片等）进一步检查话题是否匹配
     *
     * @param array $record_found 包含动态信息的数组，用于获取话题ID等信息
     * @param array $trends_talk_ids 一个包含有效话题ID的数组，用于匹配动态绑定的话题
     * @param string $type 动态的类型，默认为'text'，用于确定检查哪种类型的话题ID
     *
     * @return bool 如果动态未绑定话题或绑定的话题与给定的话题数组匹配，则返回true，否则返回false
     */
    protected static function ProcessingTrendsTaskRules($record_found, $trends_talk_ids, $type = 'text')
    {
        try {
            if (!$trends_talk = html_entity_decode($trends_talk_ids)) {
                return false;
            }
            // 动态未绑定话题，直接返回成功
            if (!($trends_talk_ids) || !is_array($trends_talk_ids)) {
                return true;
            }
            // 获取全局话题ID
            $global_talk_id = isset($record_found['talk_id']) ? intval($record_found['talk_id']) : 0;
            // 获取分类话题标识
            $mark = "{$type}_talk_id";
            // 获取分类话题ID，优先使用分类话题ID，如果没有则使用全局话题ID
            $type_talk_id = isset($record_found[$mark]) ? intval($record_found[$mark]) : $global_talk_id;
            // 未设置话题，直接返回成功
            if ($type_talk_id === 0) {
                return true;
            }
            // 检测话题是否匹配，返回匹配结果 true or false
            return in_array($type_talk_id, $trends_talk_ids);
        } catch (\Exception $e) {
            return false;
        }
    }

    /**
     * 将JSON格式的唯一标识字符串转换为数组
     *
     * 此函数负责将经过base64编码的唯一标识字符串解码并转换为数组形式
     * 如果解码或转换过程中出现任何错误，或者解码后的数据不符合预期格式，
     * 函数将返回一个包含默认值的数组
     *
     * @param string $jobs_unique_id 经过base64编码的唯一标识字符串
     * @return array 包含jobs_id和rules_key的数组
     */
    protected static function formatJsonUniqueIdStringToArray($jobs_unique_id)
    {
        $result = ['jobs_id' => 0, 'rules_key' => '', 'method' => 0];
        try {
            // 验证输入是否为有效的Base64编码
            if (empty($jobs_unique_id) || !preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $jobs_unique_id)) {
                return $result;
            }
            // 尝试将base64解码后的字符串转换为数组
            $decoded = base64_decode($jobs_unique_id);
            if ($decoded === false) {
                return $result;
            }
            $jobs_unique = XypHelper::stringToArray($decoded, '_');
            if (!$jobs_unique) {
                // 记录日志，说明为什么返回默认值
                error_log("Failed to convert decoded string to array: " . $decoded);
                return $result;
            }
            // 初始化结果数组，默认值为0和空字符串
            $result = ['jobs_id' => 0, 'rules_key' => '', 'method' => 0];
            // 根据实际情况填充结果数组
            if (isset($jobs_unique[0])) {
                $result['jobs_id'] = intval($jobs_unique[0]);
            }
            if (isset($jobs_unique[1])) {
                $result['method'] = $jobs_unique[1];
            }
            if (isset($jobs_unique[2])) {
                $result['rules_key'] = $jobs_unique[2];
            }
            return $result;
        } catch (\InvalidArgumentException $e) {
            // 记录异常信息
            error_log("InvalidArgumentException caught: " . $e->getMessage());
            return $result;
        } catch (\RuntimeException $e) {
            // 记录异常信息
            error_log("RuntimeException caught: " . $e->getMessage());
            return $result;
        }
    }

    /**
     * 处理动态规则
     *
     * 该方法用于根据记录和动态信息，判断是否满足特定的规则条件
     * 主要检查视频、图文和文本动态是否符合相应的规则，包括话题匹配、文本长度、图片数量等
     *
     * @param array $jobs 包含规则信息的数组
     * @param object $trends 动态对象，包含动态的相关信息
     *
     * @return array 包含规则检查结果的数组，如是否满足规则、动态类型和提示消息
     */
    protected static function ProcessingDailyTrendsRules($jobs, $trends)
    {
        $detail_text_length = mb_strlen($trends->detail ?? '', 'utf-8');
        $image_length = 0;
        $type = $trends->mp4_file ? 'video' : (($image_length = XypHelper::stringToArray($trends->images, ',')) ? 'image' : 'text');
        /*检测话题是否匹配*/
        if (!self::ProcessingDailyTrendsTaskRules($jobs['talk_id'], $trends->huati_text)) {
            return ['stated' => false, 'type' => $type, 'msg' => '动态未检测到话题信息'];
        }
        $push_rules = XypHelper::formatJsonStringToArray($jobs['participation_rules']);
        $stated = true;
        $msg = '检查通过';
        switch ($type) {
            case 'video':
                $stated = true;
                break;
            case 'image':
                if (isset($push_rules['image_num']) && intval($push_rules['image_num']) > count($image_length)) {
                    $stated = false;
                    $msg = '图文动态图片数量不足';
                }
                break;
            default:
                break;
        }
        if (isset($push_rules['text_num']) && intval($push_rules['text_num']) > $detail_text_length) {
            $stated = false;
            $msg = '文本动态文本字数不足';
        }
        return ['stated' => $stated, 'type' => $type, 'msg' => $msg];
    }

    /**
     * 处理动态任务规则
     *
     * 此函数用于判断动态是否符合给定的话题规则它检查动态是否绑定了特定的话题，
     * 如果绑定了，则根据动态的类型（如文本、图片等）进一步检查话题是否匹配
     *
     * @param int $talk_id 包含动态信息的数组，用于获取话题ID等信息
     * @param array $trends_talk 一个包含有效话题ID的数组，用于匹配动态绑定的话题
     * @param string $type 动态的类型，默认为'text'，用于确定检查哪种类型的话题ID
     *
     * @return bool 如果动态未绑定话题或绑定的话题与给定的话题数组匹配，则返回true，否则返回false
     */
    protected static function ProcessingDailyTrendsTaskRules($talk_id, $trends_talk)
    {

        try {
            if (!$trends_talk = html_entity_decode($trends_talk)) {
                return false;
            }
            $trends_talk = XypHelper::formatJsonStringToArray($trends_talk);
            // 动态未绑定话题，直接返回成功
            if (!($trends_talk) || !is_array($trends_talk)) {
                return false;
            }
            if (!$trends_talk_ids = array_values(array_filter(array_column($trends_talk, 'id')))) {
                return false;
            }
            // 检测话题是否匹配，返回匹配结果 true or false
            return in_array($talk_id, $trends_talk_ids);
        } catch (\Exception $e) {
            return false;
        }
    }

}